package com.iot.common.utils;

import com.alibaba.fastjson.JSONArray;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Cao.ning
 * @date 2022/8/5
 */
public class HexUtils {

    public static boolean isHex(String str){
        String regex = "^[A-Fa-f0-9]+$";
        if(str != null && str.matches(regex)){
            return true;
        }else{
            return false;
        }
    }

    public static byte[] hexStringToByte(String hex)
    {
        int length = hex.length() / 2;
        byte[] result = new byte[hex.length() / 2];
        char[] chars = hex.toCharArray();
        for (int i = 0; i < length; i++)
        {
            int pos = i*2;
            // 63E1 393B
            result[i] = (byte)(toByte(chars[pos]) << 4 | toByte(chars[pos + 1]));
        }
        return result;
    }

    public static byte toByte(char c){
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * 将byte类型的arr转换成float
     * @return
     */
    public static List<Float> byteArrayToFloatList(byte[] bytes){
        List<Float> d = new ArrayList<>(bytes.length/8);
        byte[] doubleBuffer = new byte[4];
        for(int j = 0; j < bytes.length; j += 4) {
            System.arraycopy(bytes, j, doubleBuffer, 0, doubleBuffer.length);
            d.add(bytes2FloatBig(doubleBuffer));
        }
        return d;
    }

    /**
     * 将byte类型的arr转换成double
     * @param arr
     * @return
     */
    public static List<Double> byteArrayToDoubleList(byte[] arr){
        List<Double> d = new ArrayList<>(arr.length/8);
        byte[] doubleBuffer = new byte[8];
        for(int j = 0; j < arr.length; j += 8) {
            System.arraycopy(arr, j, doubleBuffer, 0, doubleBuffer.length);
            d.add(bytes2Double(doubleBuffer));
        }
        return d;
    }

    /**
     * 将byte数组数据转换成float
     * @param arr
     * @return
     */
    public static float bytes2FloatLit(byte[] arr) {
        int accum = 0;
        accum = accum|(arr[0] & 0xff) << 0;
        accum = accum|(arr[1] & 0xff) << 8;
        accum = accum|(arr[2] & 0xff) << 16;
        accum = accum|(arr[3] & 0xff) << 24;
        return Float.intBitsToFloat(accum);
    }

    /**
     * 将byte数组数据转换成float（大端）
     * @param arr
     * @return
     */
    public static float bytes2FloatBig(byte[] arr) {
        int accum = 0;
        accum = accum|(arr[3] & 0xff) << 0;
        accum = accum|(arr[2] & 0xff) << 8;
        accum = accum|(arr[1] & 0xff) << 16;
        accum = accum|(arr[0] & 0xff) << 24;
        return Float.intBitsToFloat(accum);
    }

    /**
     * 将byte转换成double
     * @param arr
     * @return
     */
    public static double bytes2Double(byte[] arr) {
        long value = 0;
        for (int i = 0; i < 8; i++) {
            value |= ((long) (arr[i] & 0xff)) << (8 * i);
        }
        return Double.longBitsToDouble(value);
    }

    public static JSONArray bytes2FloatArray(byte[] bytes){
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        FloatBuffer floatBuffer = buffer.asFloatBuffer();
        JSONArray floatList = new JSONArray();
        for(int i =0; i<floatBuffer.capacity(); i++){
            //float f = Float.parseFloat(String.format("%.6f", floatBuffer.get(i)));
            //DecimalFormat decimalFormat = new DecimalFormat("#.000000");
            //String str = decimalFormat.format(floatBuffer.get(i));
            String str = String.valueOf(floatBuffer.get(i));
            if(str.contains("E")){
                str = str.split("E")[0];
            }
            floatList.add(Float.parseFloat(str));
        }
        return floatList;
    }

    public static List<Double> bytes2DoubleList(byte[] bytes){
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        DoubleBuffer doubleBuffer = buffer.asDoubleBuffer();
        List<Double> doubleList = new ArrayList<>();
        for(int i =0; i<doubleBuffer.capacity(); i++){
            double f = Double.parseDouble(String.format("%.6f", doubleBuffer.get(i)));
            doubleList.add(f);
        }
        return doubleList;
    }

    private final static String[] hexSymbols = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    public final static int BITS_PER_HEX_DIGIT = 4;

    public static String toHexFromByte(final byte b) {
        byte leftSymbol = (byte) ((b >>> BITS_PER_HEX_DIGIT) & 0x0f);
        byte rightSymbol = (byte) (b & 0x0f);
        return (hexSymbols[leftSymbol] + hexSymbols[rightSymbol]);

    }

    public static String toHexFromBytes(final byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return ("");
        }
        // there are 2 hex digits per byte
        StringBuilder hexBuffer = new StringBuilder(bytes.length * 2);
        // for each byte, convert it to hex and append it to the buffer
        for (int i = 0; i < bytes.length; i++) {
            hexBuffer.append(toHexFromByte(bytes[i]));
        }
        return (hexBuffer.toString());
    }

    public static String fileToHex(String file) {
        StringBuilder sb = new StringBuilder();
        try {
            FileInputStream fis = new FileInputStream(new File(file));
            BufferedWriter fos = new BufferedWriter(new FileWriter(new File("C:\\Users\\86150\\Desktop\\AA223.jpg")));
            byte[] bytes = new byte[800];
            int value = 0;
            do {
                value = fis.read(bytes);
                fos.write(toHexFromBytes(bytes));
                sb.append(toHexFromBytes(bytes));
            } while (value != -1);
            fos.flush();
            fos.close();
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

//    public static void main(String[] args) {
//        System.out.println(hexToString("ABCD"));
//        System.out.println(fileToHex("C:\\Users\\86150\\Desktop\\未标题-2.jpg"));
//        String hex = "5AA5 63E1 393B E51A E8BC C869 7F3F C82D CE3A A47E CFBC 1065 7F3F 43CF E43A 10DB C2BC CDDC 7E3F 280C E43A 1DE1 C6BC 64C3 7E3F 14A7 473B 26E8 D7BC F48A 7D3F B156 6C3B 0AFC E3BC 0A57 7C3F 9D17 8C3B BCD1 E6BC E36A 7D3F 8B3F AE3B 6835 E2BC 8855 7F3F 3131 893B 050A E0BC 7A79 7F3F 86CB 2B3B 81D0 EBBC CCBD 7E3F C67C 173B BADD FDBC E956 7E3F 9C53 093B DB9A FBBC 5321 7E3F 0BC4 BE3A B8A3 EBBC 60E0 7D3F 286D C53A 0772 F3BC 68C5 7D3F 646C 113B C30E 00BD 178D 7E3F 1347 D03A 7119 F6BC 5660 7F3F 2FF8 883A D1E5 EABC 99E9 7E3F 758D 133B 1786 EDBC 25C1 7D3F 34BC 2C3B F8A9 FABC AA5D 7D3F 8CAB DF3A 6C63 00BD C1E9 7D3F ED50 383B 3819 EEBC D2A6 7E3F A1C1 883B 0DA4 DDBC 6AF8 7E3F 827E E33A 8801 ECBC C547 7E3F E623 55BA 359F F9BC 92C2 7D3F E8EC E939 FA20 EBBC EE43 7E3F 6B27 513B E8FD D8BC 289A 7E3F 8E4E 973B 37AD DBBC E029 7E3F D30D 573B 8E3C EFBC 4F5F 7D3F 5C50 903A 490E FBBC 9552 7D3F 3FD6 DA3A A89B ECBC 4E2D 7E3F C284 573B 66E6 DFBC A2A7 7E3F 3F4B 213B 2809 F2BC E726 7E3F 1886 8839 90FE 00BD 84AB 7D3F 28A0 96B9 D5C4 EEBC BB0D 7E3F 2E0E 703A 3D7F DABC F356 7E3F 2D5A E53A 8DFC E8BC 5202 7E3F FD20 653A 7BA9 00BD 66A0 7D3F 9B14 81B9 E23B FFBC 629A 7D3F 6952 A43A 18F6 E8BC 8CF9 7D3F 9257 613B CC04 E1BC 261D 7E3F 4EBC 513B E4C7 EFBC 48E3 7D3F CC85 2F3B 2A77 F8BC 5EEE 7D3F 84B3 4B3B 026F F0BC C00A 7E3F A307 383B D218 EFBC F19C 7D3F F0DE 023B E63D F5BC 24CB 7D3F 6244 093B FA26 F1BC 7A8F 7E3F 7691 4A3B 1FB5 E2BC 7865 7E3F E2AF 7C3B 80C9 DABC 66E0 7D3F 1451 773B 0C00 EDBC 3A06 7E3F 4982 2A3B F801 03BD F8A4 7E3F 86EF 913A BEED 00BD 4C4F 7F3F E000 B23A E815 E9BC 793A 7F3F C48D 1E3B 1D9A E0BC FC09 7E3F B0F7 1C3B 06FA EDBC 969D 7D3F D3B0 0A3B B952 ECBC D634 7E3F 7D19 2A3B 5A68 D8BC F032 7E3F 3412 3B3B 6001 DDBC C42E 7E3F 0784 2F3B 7B42 F8BC 1BBE 7E3F 9512 5E3B 6E80 01BD D2BE 7E3F 325A 3D3B DE06 F6BC BE05 7E3F 1062 8DB8 B9B3 E8BC 60A8 7D3F 8CC8 F3BA 6B0B E8BC 5C9D 7D3F FCDE 09B9 A5EC EBBC E6C4 7D3F C742 2A3B 1A6C E8BC 48A7 7E3F";
        /*String hex = "5AA5 63E1 393B E51A E8BC C869 7F3F C82D \n" +
                "CE3A A47E CFBC 1065 7F3F 43CF E43A 10DB \n" +
                "C2BC CDDC 7E3F 280C E43A 1DE1 C6BC 64C3 \n" +
                "7E3F 14A7 473B 26E8 D7BC F48A 7D3F B156 \n" +
                "6C3B 0AFC E3BC 0A57 7C3F 9D17 8C3B BCD1 \n" +
                "E6BC E36A 7D3F 8B3F AE3B 6835 E2BC 8855 \n" +
                "7F3F 3131 893B 050A E0BC 7A79 7F3F 86CB \n" +
                "2B3B 81D0 EBBC CCBD 7E3F C67C 173B BADD \n" +
                "FDBC E956 7E3F 9C53 093B DB9A FBBC 5321 \n" +
                "7E3F 0BC4 BE3A B8A3 EBBC 60E0 7D3F 286D \n" +
                "C53A 0772 F3BC 68C5 7D3F 646C 113B C30E \n" +
                "00BD 178D 7E3F 1347 D03A 7119 F6BC 5660 \n" +
                "7F3F 2FF8 883A D1E5 EABC 99E9 7E3F 758D \n" +
                "133B 1786 EDBC 25C1 7D3F 34BC 2C3B F8A9 \n" +
                "FABC AA5D 7D3F 8CAB DF3A 6C63 00BD C1E9 \n" +
                "7D3F ED50 383B 3819 EEBC D2A6 7E3F A1C1 \n" +
                "883B 0DA4 DDBC 6AF8 7E3F 827E E33A 8801 \n" +
                "ECBC C547 7E3F E623 55BA 359F F9BC 92C2 \n" +
                "7D3F E8EC E939 FA20 EBBC EE43 7E3F 6B27 \n" +
                "513B E8FD D8BC 289A 7E3F 8E4E 973B 37AD \n" +
                "DBBC E029 7E3F D30D 573B 8E3C EFBC 4F5F \n" +
                "7D3F 5C50 903A 490E FBBC 9552 7D3F 3FD6 \n" +
                "DA3A A89B ECBC 4E2D 7E3F C284 573B 66E6 \n" +
                "DFBC A2A7 7E3F 3F4B 213B 2809 F2BC E726 \n" +
                "7E3F 1886 8839 90FE 00BD 84AB 7D3F 28A0 \n" +
                "96B9 D5C4 EEBC BB0D 7E3F 2E0E 703A 3D7F \n" +
                "DABC F356 7E3F 2D5A E53A 8DFC E8BC 5202 \n" +
                "7E3F FD20 653A 7BA9 00BD 66A0 7D3F 9B14 \n" +
                "81B9 E23B FFBC 629A 7D3F 6952 A43A 18F6 \n" +
                "E8BC 8CF9 7D3F 9257 613B CC04 E1BC 261D \n" +
                "7E3F 4EBC 513B E4C7 EFBC 48E3 7D3F CC85 \n" +
                "2F3B 2A77 F8BC 5EEE 7D3F 84B3 4B3B 026F \n" +
                "F0BC C00A 7E3F A307 383B D218 EFBC F19C \n" +
                "7D3F F0DE 023B E63D F5BC 24CB 7D3F 6244 \n" +
                "093B FA26 F1BC 7A8F 7E3F 7691 4A3B 1FB5 \n" +
                "E2BC 7865 7E3F E2AF 7C3B 80C9 DABC 66E0 \n" +
                "7D3F 1451 773B 0C00 EDBC 3A06 7E3F 4982 \n" +
                "2A3B F801 03BD F8A4 7E3F 86EF 913A BEED \n" +
                "00BD 4C4F 7F3F E000 B23A E815 E9BC 793A \n" +
                "7F3F C48D 1E3B 1D9A E0BC FC09 7E3F B0F7 \n" +
                "1C3B 06FA EDBC 969D 7D3F D3B0 0A3B B952 \n" +
                "ECBC D634 7E3F 7D19 2A3B 5A68 D8BC F032 \n" +
                "7E3F 3412 3B3B 6001 DDBC C42E 7E3F 0784 \n" +
                "2F3B 7B42 F8BC 1BBE 7E3F 9512 5E3B 6E80 \n" +
                "01BD D2BE 7E3F 325A 3D3B DE06 F6BC BE05 \n" +
                "7E3F 1062 8DB8 B9B3 E8BC 60A8 7D3F 8CC8 \n" +
                "F3BA 6B0B E8BC 5C9D 7D3F FCDE 09B9 A5EC \n" +
                "EBBC E6C4 7D3F C742 2A3B 1A6C E8BC 48A7 \n" +
                "7E3F ";
        if(hex.startsWith("5AA5 ")){
            hex = hex.substring(5, hex.length()).replace(" ", "").replace("\r", "").replace("\n", "");
        }
        System.out.println(hex);
        byte[] bytes = HexUtils.hexStringToByte(hex);
        JSONArray floats = HexUtils.bytes2FloatArray(bytes);
        for(Object f : floats){
            System.out.print(f + ",");
        }*/
//    }

    public static String hexToString(String hex){

        StringBuilder sb = new StringBuilder();
        StringBuilder temp = new StringBuilder();
        //49204c6f7665204a617661 split into two characters 49, 20, 4c...
        for( int i=0; i<hex.length()-1; i++ ){
            //grab the hex in pairs
            String output = hex.substring(i, (i + 1));
            //convert hex to decimal
            int decimal = Integer.parseInt(output, 16);
            //convert the decimal to character
            sb.append((char)decimal);
//            sb.append(Integer.valueOf(hex.charAt(i)));
//            temp.append(decimal);
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexString
     * @return
     */
    public static String hexString2binaryString(String hexString) {
        //16进制转10进制
        BigInteger sint = new BigInteger(hexString, 16);
        //10进制转2进制
        String result = sint.toString(2);
        //字符串反转
        return new StringBuilder(result).reverse().toString();
    }
    public static String hexString2binString(String hexString) {
        //16进制转10进制
        BigInteger sint = new BigInteger(hexString, 16);
        //10进制转2进制
        String result = sint.toString(2);
        // 前面补0
        int zeroCount = (hexString.length() * 4) - result.length();
        String prefix = "";
        for(int i = 0; i < zeroCount; i++){
            prefix += "0";
        }
        return prefix + result;
    }
    public static String longToHex(long n) {
        //StringBuffer s = new StringBuffer();
        StringBuilder sb = new StringBuilder(8);
        String a;
        char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        while(n != 0){
            sb = sb.append(b[(int) (n % 16)]);
            n = n/16;
        }
        a = sb.reverse().toString();
        while(a.length() % 4 != 0){
            a = "0" + a;
        }
        return a;
    }

    public static String reverseHex(final String hex) {
        final char[] charArray = hex.toCharArray();
        final int length = charArray.length;
        final int times = length / 2;
        for (int c1i = 0; c1i < times; c1i += 2) {
            final int c2i = c1i + 1;
            final char c1 = charArray[c1i];
            final char c2 = charArray[c2i];
            final int c3i = length - c1i - 2;
            final int c4i = length - c1i - 1;
            charArray[c1i] = charArray[c3i];
            charArray[c2i] = charArray[c4i];
            charArray[c3i] = c1;
            charArray[c4i] = c2;
        }
        return new String(charArray);
    }

    public static void main(String[] args) {
        System.out.println(hexString2binString("5A5AC73F31738601640010004000549D7E3F3D5CAD3DD8BB56BB2B9F7E3F0767AF3D08C316BB499D7E3F5467B33D001757BB9DE07E3F826EAF3D30EFADBAD9217E3F586DAF3DB028ACBA9F1A7F3F515DB13DACD38BBBF35D7F3F7F64AD3DE88717BB09DB7E3FED5CB13DCCAD8BBBA20A803FAF50B13D5C82CCBB4DE27D3FDD61A93DE0DAAABA2C207F3F4B76B33D4000AFBA80A47D3F0E7BB33D4013ADB9AB9B7F3F7D61AF3D400958BBC9DE7E3F0560AB3D00D216BBAF9B7F3FCB5DAD3DD8EA57BB185C7F3F675DAD3D189F57BBD55F7F3F3264A93DE067AEBA2B9F7E3F0767AF3D08C316BB7BE27E3FE871AD3D0010B6B96BE07D3F2A62AD3D60C115BBBD5D7E3FD95BAD3D187056BBCA5F7F3F496FAF3D301EAFBA985F7E3FF162AD3DE05816BBEB977F3F645EB53D6449ACBB19DD7F3FAB6CB13D285C18BB2ED97E3FD555B13D64B9ABBB769B7E3FD758AF3DB8788BBBF24D803F7166AD3DA80219BB0DA17E3FBA66AB3D20DEACBAA70A803F9745AB3DC854CCBB11227F3F4C72AD3D006EB8B99B5F7E3F3E5FAB3D803A16BBBFDE7E3F1D6BB13D282D17BB1B5C7F3FB459AB3DB88057BBAA1A7F3F3952AB3D18A68BBBA20A803FAF50B13D5C82CCBB15227F3F996EAB3D007BB7B9352D803F5B66B13DE00A59BB329F7E3FA25FAB3D408616BB1C227F3F3567A73DC094B5B99B5F7E3F3E5FAB3D803A16BB7D0C803FDF5EB13D2C6B8CBBE8A27E3FD26DAB3D00BFB2B94949803F104EB33DE8E8ECBB3D5A7F3F4F56AD3D28DB8BBB3E207F3FCF63A93D60D0ADBAF35D7F3F7F64AD3DE88717BB185C7F3F675DAD3D189F57BB2F9F7E3F5563AD3DA8A416BBACA27D3F916CAF3DB0F9AABA5B0E803FAA65AD3D286B18BB5C1E7F3F1C64AD3D283C17BB11227F3F4C72AD3D006EB8B9C9DE7E3F0560AB3D00D216BB369F7E3FF05BA93DE06716BB18227F3FE76AA93D0088B6B950E27D3F2B5EA73D209EAABAA61A7F3FEC55AD3D48B58BBB44A87D3F747AAB3D180BD63A07227F3F637DB33D4047BBB9B7237E3FBE70AD3D00F6AEB94CDB7F3FC956A93DD8F957BB37207F3F346BAD3DF049AEBA9DE07E3F826EAF3D30EFADBA5A5A"));
    }
}
